<template>
  <div  class="flex-container">
    <div id="problem-main">
      <!--problem main-->
      <div :padding="10" >
        <!-- 标题 -->
        <div style="justify-content:left; display: flex;align-items: center; margin-left: 20px;margin-top: -20px; margin-bottom: 10px; font-size: 25px">
          <i v-if="!star" @click="changeStar" class="el-icon-star-off" style="color:black"></i>
          <i v-if="star" @click="changeStar" class="el-icon-star-on" style="color:gold" ></i>
          <div style="margin-left:10px" >{{problem._id}}.   {{problem.title}}</div>
          <div v-if="problem.my_status === 0" style="margin-left: 300px;">
            <Alert type="success" show-icon>{{$t('m.You_have_solved_the_problem')}}</Alert>
          </div>
        </div>
        <template>
          <el-tabs id="test" v-model="activeName" type="card">
            <el-tab-pane label="题目" name="problem"></el-tab-pane>
            <el-tab-pane label="讨论" name="discussion"></el-tab-pane>
            <el-tab-pane label="提交记录" name="record"></el-tab-pane>
            <el-tab-pane label="视频讲解" name="video"></el-tab-pane>
          </el-tabs>
        </template>
        <div v-show="activeName==='problem'">
          <el-row  :gutter="20">
            <el-col :span="18">
              <!-- 题面 -->
              <v-md-preview :text="problem.description" @copy-code-success="handleCopyCodeSuccess"></v-md-preview>
              
            <!--problem main end-->
            <!-- 代码编辑器 -->
              <div :padding="20" id="submit-code" dis-hover>
                <CodeMirror :value.sync="code"
                            :languages="problem.languages"
                            :language="language"
                            :theme="theme"
                            @resetCode="onResetToTemplate"
                            @changeTheme="onChangeTheme"
                            @changeLang="onChangeLang">
                </CodeMirror>
                <!-- 状态展示 -->
                <Row type="flex" justify="space-between">
                  <Col :span="15">
                    <div class="status" v-if="statusVisible">
                      <template v-if="!this.contestID || (this.contestID && OIContestRealTimePermission)">
                        <span>{{$t('m.Status')}}</span>
                        <Tag type="dot" :color="submissionStatus.color" @click.native="handleRoute('/status/'+submissionId)">
                          {{$t('m.' + submissionStatus.text.replace(/ /g, "_"))}}
                        </Tag>
                      </template>
                      <template v-else-if="this.contestID && !OIContestRealTimePermission">
                        <Alert type="success" show-icon>{{$t('m.Submitted_successfully')}}</Alert>
                      </template>
                    </div>
                    <div v-else-if="problem.my_status === 0">
                      <Alert type="success" show-icon>{{$t('m.You_have_solved_the_problem')}}</Alert>
                    </div>
                    <div v-if="contestEnded">
                      <Alert type="warning" show-icon>{{$t('m.Contest_has_ended')}}</Alert>
                    </div>
                  </Col>

                  <Col :span="8">
                    <template v-if="captchaRequired">
                      <div class="captcha-container">
                        <Tooltip v-if="captchaRequired" content="Click to refresh" placement="top">
                          <img :src="captchaSrc" @click="getCaptchaSrc"/>
                        </Tooltip>
                        <Input v-model="captchaCode" class="captcha-code"/>
                      </div>
                    </template>
                    <Button type="success" :loading="submitting" @click="submitCode"
                      :disabled="problemSubmitDisabled || submitted"
                      class="fl-right">
                      <span v-if="submitting">{{$t('m.Submitting')}}</span>
                      <span v-else>提交答案</span>
                    </Button>
                    <Button type="primary"  :loading="submitting" @click="testCode"
                        :disabled="problemSubmitDisabled || submitted"
                        class="fl-right" style="margin-right: 20px;">
                        <span v-if="testting">运行中</span>
                        <span v-else>运行自测</span>
                    </Button>
                  </Col>
                </Row>
                <!-- 自测面板 -->
                <Row :gutter="24" style="margin-top: 10px;margin-right: -20px; margin-left: -20px; ">
                  <Col span=12>
                    <!-- dis-hover 悬浮时阴影  -->
                    <Card :bordered="false" :dis-hover="true">
                      <p slot="title" style="font-size: 16px;">输入</p>
                      <Input v-model="input" type="textarea" :autosize="{minRows: 5,maxRows: 5}" placeholder="输入测试数据" />
                    </Card>
                  </Col>
                  <Col span=12>
                    <Card :bordered="false" :dis-hover="true">
                      <p slot="title" style="font-size: 16px;">输出</p>
                      <p slot="extra">Time: {{time_cost}}ms</p>
                      <p slot="extra">Memory: {{memory_cost}}MB</p>
                      <Input v-model="output" readonly type="textarea" :autosize="{minRows: 5,maxRows: 5}"  />
                    </Card>
                  </Col>
                </Row>
              </div>
            </el-col>

            <el-col :span="6">
              <Card id="info">
                <div slot="title" class="header">
                  <Icon type="information-circled"></Icon>
                  <span class="card-title">{{$t('m.Information')}}</span>
                </div>
                <ul>
                  <li><p>ID</p>
                    <p>{{problem._id}}</p></li>
                  <li>
                    <p>{{$t('m.Time_Limit')}}</p>
                    <p>{{problem.time_limit}}MS</p></li>
                  <li>
                    <p>{{$t('m.Memory_Limit')}}</p>
                    <p>{{problem.memory_limit}}MB</p></li>
                
                  <li>
                    <p>{{$t('m.IOMode')}}</p>
                    <p>{{problem.io_mode.io_mode}}</p>
                  </li>
                  <li>
                    <p>{{$t('m.Created')}}</p>
                    <p>{{problem.created_by.username}}</p></li>
                  <li v-if="problem.difficulty">
                    <p>{{$t('m.Level')}}</p>
                    <p>{{$t('m.' + problem.difficulty)}}</p></li>
                  <li v-if="problem.total_score">
                    <p>{{$t('m.Score')}}</p>
                    <p>{{problem.total_score}}</p>
                  </li>
                  <li>
                    <p>{{$t('m.Tags')}}</p>
                    <p>
                      <Poptip trigger="hover" placement="left-end">
                        <a>{{$t('m.Show')}}</a>
                        <div slot="content">
                          <Tag v-for="tag in problem.tags" :key="tag">{{tag}}</Tag>
                        </div>
                      </Poptip>
                    </p>
                  </li>
                </ul>
              </Card>

              <Card id="pieChart" :padding="0" v-if="!this.contestID || OIContestRealTimePermission">
                <div slot="title">
                  <Icon type="ios-analytics"></Icon>
                  <span class="card-title">{{$t('m.Statistic')}}</span>
                  <!-- <Button type="ghost" size="small" id="detail" @click="graphVisible = !graphVisible">Details</Button> -->
                </div>
                <div class="echarts">
                  <ECharts :options="pie"></ECharts>
                </div>
              </Card>
            </el-col>
          </el-row>
        </div>
        <div v-if="activeName==='discussion'">
          <ProblemDiscussion :problemID="problem._id" :problemid="problem.id">
          </ProblemDiscussion>
        </div>
        <div v-if="activeName==='record'">
          <ProblemRecord :problemID="problem._id">
          </ProblemRecord>
        </div>
        <div v-if="activeName==='video'">
          <ProblemVideo :fileID="problem.video">
          </ProblemVideo>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  import {mapGetters, mapActions} from 'vuex'
  import {types} from '../../../../store'
  import CodeMirror from '@oj/components/CodeMirror.vue'
  import storage from '@/utils/storage'
  import {FormMixin} from '@oj/components/mixins'
  import ProblemDiscussion from '../problem/ProblemDiscussion.vue'
  import ProblemRecord from '../problem/ProblemRecord.vue'
  import ProblemVideo from '../problem/ProblemVideo.vue'
  import {JUDGE_STATUS, CONTEST_STATUS, buildProblemCodeKey} from '@/utils/constants'
  import api from '@oj/api'
  import {pie, largePie} from '../problem/chartData'

  // 只显示这些状态的图形占用
  const filtedStatus = ['-1', '-2', '0', '1', '2', '3', '4', '8']

  export default {
    name: 'Problem',
    props: {
      problemID: {
        type: String,
        required: true
      }
    },
    components: {
      CodeMirror,
      ProblemDiscussion,
      ProblemRecord,
      ProblemVideo
    },
    mixins: [FormMixin],
    data () {
      return {
        activeName: 'problem',
        testCaptchaRequired: false,
        testCaptchaCode: '',
        testCaptchaSrc: '',
        testting: false,
        input: '',
        output: '',
        statusVisible: false,
        captchaRequired: false,
        graphVisible: false,
        captchaCode: '',
        captchaSrc: '',
        contestID: '',
        submitting: false,
        code: '',
        language: 'C++',
        theme: 'solarized',
        submissionId: '',
        submitted: false,
        result: {
          result: 9
        },
        problem: {
          id: 0,
          title: '',
          description: '',
          hint: '',
          my_status: '',
          template: {},
          languages: [],
          created_by: {
            username: ''
          },
          tags: [],
          io_mode: {'io_mode': 'Standard IO'}
        },
        pie: pie,
        largePie: largePie,
        // echarts 无法获取隐藏dom的大小，需手动指定
        largePieInitOpts: {
          width: '500',
          height: '480'
        },
        time_cost: 0,
        memory_cost: 0,
        star: 0
      }
    },
    beforeRouteEnter (to, from, next) {
      let problemCode = storage.get(buildProblemCodeKey(to.params.problemID, to.params.contestID))
      if (problemCode) {
        next(vm => {
          vm.language = problemCode.language
          vm.code = problemCode.code
          vm.theme = problemCode.theme
        })
      } else {
        next()
      }
    },
    mounted () {
      this.$store.commit(types.CHANGE_CONTEST_ITEM_VISIBLE, {menu: false})
      this.init()
    },
    methods: {
      ...mapActions(['changeDomTitle']),
      init () {
        this.$Loading.start()
        api['getProblem'](this.problemID, this.contestID).then(res => {
          this.$Loading.finish()
          let problem = res.data.data
          this.changeDomTitle({title: problem.title})
          problem.languages = problem.languages.sort()
          this.problem = problem
          console.log(this.problem)
          if (problem.statistic_info) {
            this.changePie(problem)
          }

          // 在beforeRouteEnter中修改了, 说明本地有code，无需加载template
          if (this.code !== '') {
            return
          }
          // try to load problem template
          this.language = this.problem.languages[0]
          let template = this.problem.template
          if (template && template[this.language]) {
            this.code = template[this.language]
          }

          if (this.user.id) {
            this.getStarStatus()
          }
          // this.problem.description = '$$\\sum_{i=1}^{n}{a_i}$$'
        }, () => {
          this.$Loading.error()
        })
      },
      getStarStatus () {
        let query = {}
        query.type = 'problem'
        query.id = this.problem.id
        console.log(this.problem.id)
        api.starExists(query).then(res => {
          // console.log(res)
          this.star = res.data.data
        })
      },
      changeStar () {
        if (!this.star) {
          let par = {}
          par.problem_id = this.problem.id
          api.createStar(par).then(res => {
            this.star = !this.star
          })
        } else {
          let par = {}
          par.star_id = this.problem.id
          par.type = 'problem'
          api.deleteStar(par).then(res => {
            this.star = !this.star
          })
        }
      },
      changePie (problemData) {
        // 只显示特定的一些状态
        for (let k in problemData.statistic_info) {
          if (filtedStatus.indexOf(k) === -1) {
            delete problemData.statistic_info[k]
          }
        }
        let acNum = problemData.accepted_number
        let data = [
          {name: 'WA', value: problemData.submission_number - acNum},
          {name: 'AC', value: acNum}
        ]
        this.pie.series[0].data = data
        // 只把大图的AC selected下，这里需要做一下deepcopy
        let data2 = JSON.parse(JSON.stringify(data))
        data2[1].selected = true
        this.largePie.series[1].data = data2

        // 根据结果设置legend,没有提交过的legend不显示
        let legend = Object.keys(problemData.statistic_info).map(ele => JUDGE_STATUS[ele].short)
        if (legend.length === 0) {
          legend.push('AC', 'WA')
        }
        this.largePie.legend.data = legend

        // 把ac的数据提取出来放在最后
        let acCount = problemData.statistic_info['0']
        delete problemData.statistic_info['0']

        let largePieData = []
        Object.keys(problemData.statistic_info).forEach(ele => {
          largePieData.push({name: JUDGE_STATUS[ele].short, value: problemData.statistic_info[ele]})
        })
        largePieData.push({name: 'AC', value: acCount})
        this.largePie.series[0].data = largePieData
      },
      handleRoute (route) {
        this.$router.push(route)
      },
      onChangeLang (newLang) {
        if (this.problem.template[newLang]) {
          if (this.code.trim() === '') {
            this.code = this.problem.template[newLang]
          }
        }
        this.language = newLang
      },
      onChangeTheme (newTheme) {
        this.theme = newTheme
      },
      onResetToTemplate () {
        this.$Modal.confirm({
          content: this.$i18n.t('m.Are_you_sure_you_want_to_reset_your_code'),
          onOk: () => {
            let template = this.problem.template
            if (template && template[this.language]) {
              this.code = template[this.language]
            } else {
              this.code = ''
            }
          }
        })
      },
      checkSubmissionStatus () {
        // 使用setTimeout避免一些问题
        if (this.refreshStatus) {
          // 如果之前的提交状态检查还没有停止,则停止,否则将会失去timeout的引用造成无限请求
          clearTimeout(this.refreshStatus)
        }
        const checkStatus = () => {
          let id = this.submissionId
          api.getSubmission(id).then(res => {
            this.result = res.data.data
            if (Object.keys(res.data.data.statistic_info).length !== 0) {
              this.submitting = false
              this.submitted = false
              clearTimeout(this.refreshStatus)
              this.init()
            } else {
              this.refreshStatus = setTimeout(checkStatus, 2000)
            }
          }, res => {
            this.submitting = false
            clearTimeout(this.refreshStatus)
          })
        }
        this.refreshStatus = setTimeout(checkStatus, 2000)
      },
      submitCode () {
        if (this.code.trim() === '') {
          this.$error(this.$i18n.t('m.Code_can_not_be_empty'))
          return
        }
        this.submissionId = ''
        this.result = {result: 9}
        this.submitting = true
        let data = {
          problem_id: this.problem.id,
          language: this.language,
          code: this.code
        }
        if (this.captchaRequired) {
          data.captcha = this.captchaCode
        }
        const submitFunc = (data, detailsVisible) => {
          this.statusVisible = true
          api.submitCode(data).then(res => {
            this.submissionId = res.data.data && res.data.data.submission_id
            // 定时检查状态
            this.submitting = false
            if (!detailsVisible) {
              this.$Modal.success({
                title: this.$i18n.t('m.Success'),
                content: this.$i18n.t('m.Submit_code_successfully')
              })
              return
            }
            this.submitted = true
            this.checkSubmissionStatus()
          }, res => {
            this.getCaptchaSrc()
            if (res.data.data.startsWith('Captcha is required')) {
              this.captchaRequired = true
            }
            this.submitting = false
            this.statusVisible = false
          })
        }
        submitFunc(data, true)
      },
      testCode () {
        if (this.code.trim() === '') {
          this.$error('不能测试空代码')
          return
        }
        this.testting = true
        this.result = {result: 9}
        let data = {
          language: this.language,
          code: this.code,
          input: this.input
        }
        if (this.testCaptchaRequired) {
          data.captcha = this.testCaptchaCode
        }
        api.IDE(data).then(res => {
          var resdata = res.data.data
          if (res.data.data.err) {
            this.output = resdata.data
            this.testting = false
            this.time_cost = 'Error '
            this.memory_cost = 'Error '
          } else {
            this.output = resdata.data[0]['output']
            this.testting = false
            this.time_cost = resdata.data[0]['real_time']
            this.memory_cost = parseInt(resdata.data[0]['memory'] / 1024 / 1024)
          }
        }, () => {
          this.testting = false
        })
      },
      onCopy (event) {
        this.$success('Code copied')
      },
      onCopyError (e) {
        this.$error('Failed to copy code')
      },
      handleCopyCodeSuccess () {
        this.$notify({
          title: '复制成功',
          type: 'success',
          duration: 2000
        })
      }
    },
    computed: {
      ...mapGetters(['problemSubmitDisabled', 'contestRuleType', 'OIContestRealTimePermission', 'contestStatus', 'user']),
      contest () {
        return this.$store.state.contest.contest
      },
      contestEnded () {
        return this.contestStatus === CONTEST_STATUS.ENDED
      },
      submissionStatus () {
        return {
          text: JUDGE_STATUS[this.result.result]['name'],
          color: JUDGE_STATUS[this.result.result]['color']
        }
      },
      submissionRoute () {
        if (this.contestID) {
          return {name: 'contest-submission-list', query: {problemID: this.problemID}}
        } else {
          return {name: 'submission-list', query: {problemID: this.problemID}}
        }
      },
      discussionRoute () {
        if (this.contestID) {
          return {name: 'contest-submission-list', query: {problemID: this.problemID}}
        } else {
          return {name: 'discussion-list', query: {problem_id: this.problemID}}
        }
      }
    },
    beforeRouteLeave (to, from, next) {
      // 防止切换组件后仍然不断请求
      clearInterval(this.refreshStatus)

      this.$store.commit(types.CHANGE_CONTEST_ITEM_VISIBLE, {menu: true})
      storage.set(buildProblemCodeKey(this.problem._id, from.params.contestID), {
        code: this.code,
        language: this.language,
        theme: this.theme
      })
      next()
    },
    watch: {
      '$route' () {
        this.init()
      }
    }
  }
</script>

<style lang="less">
  .card-title {
    margin-left: 8px;
  }

  .flex-container {
    margin-top: 30px;
    #problem-main {
      flex: auto;
      margin-right: 18px;
    }
    #right-column {
      flex: none;
      width: 220px;
    }
  }

  #problem-content {
    margin-top: -50px;
    .title {
      font-size: 20px;
      font-weight: 400;
      margin: 25px 0 8px 0;
      color: #3091f2;
      .copy {
        padding-left: 8px;
      }
    }
    p.content {
      margin-left: 25px;
      margin-right: 20px;
      font-size: 15px
    }
    .sample {
      align-items: stretch;
      &-input, &-output {
        width: 50%;
        flex: 1 1 auto;
        display: flex;
        flex-direction: column;
        margin-right: 5%;
      }
      pre {
        flex: 1 1 auto;
        align-self: stretch;
        border-style: solid;
        background: transparent;
      }
    }
  }

  #submit-code {
    margin-top: 20px;
    margin-bottom: 20px;
    .status {
      float: left;
      span {
        margin-right: 10px;
        margin-left: 10px;
      }
    }
    .captcha-container {
      display: inline-block;
      .captcha-code {
        width: auto;
        margin-top: -20px;
        margin-left: 20px;
      }
    }
  }

  #info {
    margin-bottom: 20px;
    margin-top: 20px;
    ul {
      list-style-type: none;
      li {
        border-bottom: 1px dotted #e9eaec;
        margin-bottom: 10px;
        p {
          display: inline-block;
        }
        p:first-child {
          width: 90px;
        }
        p:last-child {
          float: right;
        }
      }
    }
  }

  .fl-right {
    float: right;
  }

  #pieChart {
    .echarts {
      height: 250px;
      width: 210px;
    }
    #detail {
      position: absolute;
      right: 10px;
      top: 10px;
    }
  }

  #pieChart-detail {
    margin-top: 20px;
    width: 500px;
    height: 480px;
  }

  .el-tabs__item { 
    font-size: 18px;
    color: #2f323e;
  }
</style>

